package fr.perso.spring.jmx;
//package fr.perso.spring;
//
//import java.lang.reflect.InvocationHandler;
//import java.lang.reflect.InvocationTargetException;
//import java.lang.reflect.Method;
//import java.lang.reflect.Proxy;
//import java.util.Arrays;
//import java.util.HashMap;
//import java.util.Hashtable;
//import java.util.Map;
//
//import javax.management.MBeanServer;
//import javax.management.MalformedObjectNameException;
//import javax.management.ObjectName;
//
//import org.slf4j.Logger;
//import org.slf4j.LoggerFactory;
//import org.springframework.beans.factory.FactoryBean;
//import org.springframework.beans.factory.InitializingBean;
//import org.springframework.beans.factory.config.AbstractFactoryBean;
//import org.springframework.util.Assert;
//import org.springframework.util.ClassUtils;
//
///**
// * <p>
// * Instantiate {@link MBeanServer} which add configured extra attributes to each {@link ObjectName} passed as method parameter. The goal is
// * to prevent collisions between MBeans declared in different web applications.
// * </p>
// * <p>
// * Sample : EHCache's {@link net.sf.ehcache.management.ManagementService} will register Hibernate's
// * {@linkplain org.hibernate.cache.StandardQueryCache} as
// * <code>net.sf.ehcache:CacheManager=my-cachemanager,name=org.hibernate.cache.StandardQueryCache,type=CacheStatistics</code> that could
// * collide with other applications and this MBeanServer will add the <code>path</code> attribute to prevent problems :
// * <code>net.sf.ehcache:CacheManager=my-cachemanager,name=org.hibernate.cache.StandardQueryCache,type=CacheStatistics,path=/my-application</code>
// * .
// * </p>
// * <p>
// * This {@link FactoryBean} doesn't extend {@link AbstractFactoryBean} due to <a
// * href="http://jira.springframework.org/browse/SPR-4968">SPR-4968 : Error "Singleton instance not initialized yet" triggered by toString
// * call in case of circular references</a>
// * </p>
// * 
// * @author <a href="mailto:cyrille.leclerc@pobox.com">Cyrille Le Clerc</a>
// */
//public class EnhancedMBeanServerFactory implements FactoryBean, InitializingBean {
//    
//    private final static Logger logger = LoggerFactory.getLogger(EnhancedMBeanServerFactory.class);
//    
//    protected MBeanServer instance;
//    
//    protected MBeanServer mbeanServer;
//
//    protected Map<String, String> objectNameExtraAttributes = new HashMap<String, String>();
//    
//    @Override
//    public void afterPropertiesSet() throws Exception {
//        Assert.notNull(this.mbeanServer, "mbeanServer can NOT be null");
//        logger.trace("Extra objectname attributes : {}" + this.objectNameExtraAttributes);
//    }
//    
//    @Override
//    public Object getObject() throws Exception {
//        if (instance == null) {
//            InvocationHandler invocationHandler = new InvocationHandler() {
//                /**
//                 * <p>
//                 * Copy the given <code>objectName</code> adding <code>objectNameExtraAttributes</code>
//                 * </p>
//                 */
//                protected ObjectName addAttributesToObjectName(ObjectName objectName) throws MalformedObjectNameException {
//                    Hashtable<String, String> table = new Hashtable<String, String>(objectName.getKeyPropertyList());
//                    table.putAll(objectNameExtraAttributes);
//                    
//                    ObjectName result = ObjectName.getInstance(objectName.getDomain(), table);
//                    logger.trace("addPropertiesToObjectName({}): {}", objectName, result);
//                    
//                    return result;
//                }
//                
//                @Override
//                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//                    Object[] modifiedArgs = args.clone();
//                    for (int i = 0; i < modifiedArgs.length; i++) {
//                        Object arg = modifiedArgs[i];
//                        if (arg instanceof ObjectName) {
//                            ObjectName objectName = (ObjectName)arg;
//                            modifiedArgs[i] = addAttributesToObjectName(objectName);
//                        }
//                    }
//                    if (logger.isDebugEnabled()) {
//                        logger.debug(method + " : " + Arrays.asList(modifiedArgs));
//                    }
//                    try {
//                        return method.invoke(mbeanServer, modifiedArgs);
//                    } catch (InvocationTargetException ite) {
//                        throw ite.getCause();
//                    }
//                }
//            };
//            instance = (MBeanServer)Proxy.newProxyInstance(ClassUtils.getDefaultClassLoader(), new Class[] {
//                MBeanServer.class
//            }, invocationHandler);
//            
//        }
//        return instance;
//    }
//    
//    @Override
//    public Class<? extends MBeanServer> getObjectType() {
//        return MBeanServer.class;
//    }
//    
//    @Override
//    public boolean isSingleton() {
//        return true;
//    }
//    
//    public void setMbeanServer(MBeanServer mbeanServer) {
//        this.mbeanServer = mbeanServer;
//    }
//    
//    public void setObjectNameExtraAttributes(Map<String, String> objectNameExtraAttributes) {
//        this.objectNameExtraAttributes = objectNameExtraAttributes;
//    }
//}